//===============================================================================
// Microsoft patterns & practices
// Mobile Client Software Factory - July 2006
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Net;
using Microsoft.Practices.TestUtilities;
using Microsoft.Practices.Mobile.Configuration;

namespace Microsoft.Practices.Mobile.EndpointCatalog.Tests
{
	[TestClass]
	public class EndpointCatalogFixture
	{
		[TestInitialize]
		public void InitializeConfigurationManager()
		{
			ConfigurationManager.ClearCache();
			ConfigurationManager.ConfigFileName = "App.config";
		}

		[TestMethod]
		public void AddressExistForNullNetworkAndValidEndpointWithoutDefaultReturnsFalse()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();

			Assert.IsFalse(catalog.AddressExistsForEndpoint("NoDefault", null));
		}


		[TestMethod]
		public void AddressExistForAnEndpointReturnsTrueIfItExists()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();

			Assert.IsTrue(catalog.AddressExistsForEndpoint("MyHost", "Work"));
			Assert.IsTrue(catalog.AddressExistsForEndpoint("MyHost", "Internet"));
			Assert.IsTrue(catalog.AddressExistsForEndpoint("MyHost", "UseTheDefaultNetwork"), "EndpointCatalog is not using the Default config");
			Assert.IsTrue(catalog.AddressExistsForEndpoint("NoDefault", "Work"));
			Assert.IsTrue(catalog.AddressExistsForEndpoint("NoDefault", "Internet"));
		}

		[TestMethod]
		public void AddressExistForAnEndpointReturnsFalseIfItDoesntExist()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();

			Assert.IsFalse(catalog.AddressExistsForEndpoint("MissingEndpoint", "Work"));
			Assert.IsFalse(catalog.AddressExistsForEndpoint("NoDefault", "MissingNetworkAndNoDefault"));
		}

		[TestMethod]
		public void GetAddressGetsRightAddress()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();

			Assert.AreEqual(@"http://default/MyHost", catalog.GetAddressForEndpoint("MyHost", "UseTheDefault"));
			Assert.AreEqual(@"http://internet/MyHost", catalog.GetAddressForEndpoint("MyHost", "Internet"));
			Assert.AreEqual(@"http://work/MyHost", catalog.GetAddressForEndpoint("MyHost", "Work"));
			Assert.AreEqual(@"http://internet/NoDefault", catalog.GetAddressForEndpoint("NoDefault", "Internet"));
			Assert.AreEqual(@"http://work/NoDefault", catalog.GetAddressForEndpoint("NoDefault", "Work"));
		}

		[TestMethod]
		public void GetAddressGetsThrowsKeyNotFoundExceptionIfEndpointDoesntExists()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();
			ExtendedAssert.Throws<KeyNotFoundException>(
				delegate { catalog.GetAddressForEndpoint("MissingEndpoint", "Network"); });
		}

		[TestMethod]
		public void GetAddressGetsThrowsKeyNotFoundExceptionIfConfigurationDoesntExists()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();
			ExtendedAssert.Throws<KeyNotFoundException>(
				delegate { catalog.GetAddressForEndpoint("NoDefault", "MissingNetwork"); });
		}

		[TestMethod]
		public void GetAccountNameGetsRightCredentialsAccountName()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();
			//AccountName
			Assert.AreEqual(@"defaultCredentials", catalog.GetAccountNameForEndpoint("MyHost", "UseTheDefault"));
			Assert.AreEqual(@"peter", catalog.GetAccountNameForEndpoint("MyHost", "Internet"));
			Assert.AreEqual(@"chris", catalog.GetAccountNameForEndpoint("MyHost", "Work"));
			Assert.AreEqual(@"chris", catalog.GetAccountNameForEndpoint("NoDefault", "Internet"));
			Assert.AreEqual(@"peter", catalog.GetAccountNameForEndpoint("NoDefault", "Work"));
		}


		[TestMethod]
		public void GetAccountNameThrowsKeyNotFoundExceptionIfEndpointDoesntExists()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();
			ExtendedAssert.Throws<KeyNotFoundException>(
				delegate { catalog.GetAccountNameForEndpoint("MissingEndpoint", "Network"); });
		}

		[TestMethod]
		public void GetAccountNameThrowsKeyNotFoundExceptionIfConfigurationDoesntExists()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();
			ExtendedAssert.Throws<KeyNotFoundException>(
				delegate { catalog.GetAccountNameForEndpoint("NoDefault", "MissingNetwork"); });
		}

		[TestMethod]
		public void EmptyEndpointNameRegistrationShouldThrowsAnArgumentException()
		{
			EndpointCatalog catalog = new EndpointCatalog();
			Endpoint endpoint = new Endpoint(""); //Emptyname endpoint
			ExtendedAssert.Throws<ArgumentException>(
				delegate { catalog.SetEndpoint(endpoint); });//Should throws an ArgumentException
		}

		[TestMethod]
		public void NullEndpointNameRegistrationShouldThrowsAnArgumentException()
		{
			EndpointCatalog catalog = new EndpointCatalog();
			Endpoint endpoint = new Endpoint(null);
			ExtendedAssert.Throws<ArgumentException>(
				delegate { catalog.SetEndpoint(endpoint); }); //Should throws an ArgumentException
		}

		[TestMethod]
		public void NullEndpointRegistrationShouldThrowsAnArgumentException()
		{
			EndpointCatalog catalog = new EndpointCatalog();
			ExtendedAssert.Throws<ArgumentNullException>(
				delegate { catalog.SetEndpoint(null); });
		}

		[TestMethod]
		public void ModifyingDefaultEndpointConfigurationReplacePreviousEndpointConfigurationDefinedAsDefault()
		{
			EndpointCatalog catalog = new EndpointCatalog();

			Endpoint endpoint = new Endpoint("Endpoint");
			EndpointConfig ec = new EndpointConfig("URL1", "account");
			endpoint.Default = ec;	//Default configuration for endpoint "Endpoint"

			catalog.SetEndpoint(endpoint);

			Endpoint endpoint2 = new Endpoint("Endpoint");
			EndpointConfig ec2 = new EndpointConfig("URL2", "newaccount");
			endpoint2.Default = ec2; //New default configuration for endpoint "Endpoint"

			catalog.SetEndpoint(endpoint2);

			Assert.AreEqual(1, catalog.Count);
			Assert.AreEqual("newaccount", catalog.GetAccountNameForEndpoint("Endpoint", null));

		}

		[TestMethod]
		public void ModifyingEndpointOverridesPreviousOne()
		{
			EndpointCatalog catalog = new EndpointCatalog();

			Endpoint newEndpoint = new Endpoint("Endpoint");
			newEndpoint.SetConfiguration("Network", new EndpointConfig("Address"));

			catalog.SetEndpoint(newEndpoint);

			Endpoint endpoint = new Endpoint("Endpoint");
			endpoint.SetConfiguration("Network One", new EndpointConfig("Address One"));
			endpoint.SetConfiguration("Network Two", new EndpointConfig("Address Two"));

			catalog.SetEndpoint(endpoint);

			Assert.AreEqual(1, catalog.Count);
			Assert.AreEqual("Address One", catalog.GetAddressForEndpoint("Endpoint", "Network One"));
			Assert.AreEqual("Address Two", catalog.GetAddressForEndpoint("Endpoint", "Network Two"));

		}

		[TestMethod]
		public void GetAccountNameForNullNetworkThrowsKeyNotFoundExceptionIfThereIsNotDefaultConfiguration()
		{
			EndpointCatalog catalog = CreateEndpointCatalog();
			ExtendedAssert.Throws<KeyNotFoundException>(
				delegate { catalog.GetAccountNameForEndpoint("NoDefault", null); });
		}

        [TestMethod]
        public void GetAddressForNullNetworkReturnsDefaultConfiguration()
        {
            EndpointCatalog catalog = CreateEndpointCatalog();
            var address = catalog.GetAddressForEndpoint("MyHost", null);
            Assert.AreEqual("http://default/MyHost", address);
        }

        [TestMethod]
        public void GetAddressForEmptyNetworkReturnsDefaultConfiguration()
        {
            EndpointCatalog catalog = CreateEndpointCatalog();
            var address = catalog.GetAddressForEndpoint("MyHost", String.Empty);
            Assert.AreEqual("http://default/MyHost", address);
        }

        [TestMethod]
        public void GetAccountNameForNullNetworkReturnsDefaultConfiguration()
        {
            EndpointCatalog catalog = CreateEndpointCatalog();
            var account = catalog.GetAccountNameForEndpoint("MyHost", null);
            Assert.AreEqual("defaultCredentials", account);
        }

        [TestMethod]
        public void GetAccountNameForEmptyNetworkReturnsDefaultConfiguration()
        {
            EndpointCatalog catalog = CreateEndpointCatalog();
            var account = catalog.GetAccountNameForEndpoint("MyHost", String.Empty);
            Assert.AreEqual("defaultCredentials", account);
        }


        private EndpointCatalog CreateEndpointCatalog()
		{
			EndpointCatalog catalog;
			using (TestResourceFile resFile = new TestResourceFile(this, @"App.config"))
			{
				IEndpointCatalogFactory factory = new EndpointCatalogFactory("Endpoints");
				catalog = factory.CreateCatalog() as EndpointCatalog;
			}
			return catalog;
		}

	}
}
